﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace EasyMapping.Common
{
    public class ReflectionCache
    {
        private static Dictionary<string, PropertyInfo[]> _propertyInfoCache = new Dictionary<string, PropertyInfo[]>();
        private static Dictionary<string, ConstructorInfo> _constructorInfoCache = new Dictionary<string, ConstructorInfo>();
        private static  volatile object SyncRoot = new object(); 

        public static PropertyInfo[] GetPropertyInfo(Type type)
        {
            if (type == null)
            {
                throw new ArgumentException("Parameter should not be null");
            }
            PropertyInfo[] target;
            if (_propertyInfoCache.TryGetValue(type.FullName, out target))
            {
                return target;
            }
            else 
            {
                lock (SyncRoot)
                {
                    PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    _propertyInfoCache.Add(type.FullName, properties);
                    target = properties;
                }
                return target;
            }         
        }

        public static ConstructorInfo GetConstructorInfo(Type type)
        {
            if (type == null)
            {
                throw new ArgumentException("Parameter should not be null");
            }
            ConstructorInfo target;
            if (_constructorInfoCache.TryGetValue(type.FullName, out target))
            {
                return target;
            }
            else
            {
                lock (SyncRoot)
                {
                    ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
                    if (constructor == null)
                    {
                        foreach (var item in type.GetConstructors(BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.Instance))
                        {
                            if (item != null)
                            {
                                constructor = item;
                                break;
                            }
                        }
                    }
                    _constructorInfoCache.Add(type.FullName, constructor);
                    target = constructor;
                }
                return target;
            }
        }
    }
}
